<!-- @format -->

<template>
  <div>
    <transition name="message-fade">
      <div
        v-if="visible"
        :class="['lg-message', `lg-message--${type}`, customClass]"
        :style="[customStyle, { top: `${verticalOffset}px` }]"
        @mouseenter="clearTimer"
        @mouseleave="startTimer"
      >
        <div class="lg-message__content">
          <i :class="iconClass"></i>
          <span class="lg-message__text">{{ message }}</span>
        </div>

        <div
          v-if="showClose"
          class="lg-message__close el-icon-close"
          @click="close"
        >
          ❌
        </div>
      </div>
    </transition>
  </div>
</template>

<script lang="ts" setup>
  import { ref, computed, onMounted, onBeforeUnmount } from 'vue';

  interface MessageProps {
    id?: string;
    message?: string;
    type?: 'success' | 'warning' | 'error' | 'info';
    duration?: number;
    showClose?: boolean;
    onClose?: () => void;
    offset?: number;
    customClass?: string;
    customStyle?: object;
    center?: boolean;
    verticalOffset?: number;
  }

  const props = withDefaults(defineProps<MessageProps>(), {
    id: '',
    message: '',
    type: 'info',
    duration: 3000,
    showClose: false,
    onClose: () => {},
    offset: 20,
    customClass: '',
    customStyle: () => ({}),
    center: false,
    verticalOffset: 20,
  });

  const visible = ref(false);
  const timer = ref<number | null>(null);
  const verticalOffset = ref(props.verticalOffset);

  const iconClass = computed(() => {
    const typeMap = {
      success: 'el-icon-success',
      warning: 'el-icon-warning',
      error: 'el-icon-error',
      info: 'el-icon-info',
    };
    return typeMap[props.type];
  });

  const close = () => {
    visible.value = false;
    if (props.onClose) {
      props.onClose();
    }
  };

  const clearTimer = () => {
    if (timer.value) {
      clearTimeout(timer.value);
      timer.value = null;
    }
  };

  const startTimer = () => {
    if (props.duration > 0) {
      timer.value = window.setTimeout(() => {
        close();
      }, props.duration);
    }
  };

  onMounted(() => {
    visible.value = true;
    startTimer();
  });

  onBeforeUnmount(() => {
    clearTimer();
  });

  defineExpose({
    close,
    verticalOffset,
  });
</script>

<style lang="scss" scoped>
  .lg-message {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    min-width: 380px;
    padding: 15px 20px;
    border-radius: 20px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    background-color: #fff;
    transition:
      opacity 0.3s,
      transform 0.3s,
      top 0.3s;
    overflow: hidden;
    display: flex;
    align-items: center;
    z-index: 9999;

    &__content {
      display: flex;
      align-items: center;
      flex: 1;
    }

    &__text {
      margin-left: 10px;
      font-size: 16px;
      line-height: 1.5;
      color: #333;
    }

    &__close {
      font-size: 18px;
      color: #999;
      cursor: pointer;
      &:hover {
        color: #666;
      }
    }

    i {
      font-size: 20px;
    }

    &--success {
      background-color: #f0f9eb;
      border: 1px solid #e1f3d8;
      i {
        color: #67c23a;
      }
    }

    &--warning {
      background-color: #fdf6ec;
      border: 1px solid #faecd8;
      i {
        color: #e6a23c;
      }
    }

    &--error {
      background-color: #fef0f0;
      border: 1px solid #fde2e2;
      i {
        color: $main;
      }
    }

    &--info {
      background-color: #f4f4f5;
      border: 1px solid #ebeef5;
      i {
        color: #909399;
      }
    }
  }

  .message-fade-enter-active,
  .message-fade-leave-active {
    transition:
      opacity 0.3s,
      transform 0.3s;
  }

  .message-fade-enter-from,
  .message-fade-leave-to {
    opacity: 0;
    transform: translate(-50%, -20px);
  }

  @media screen and (max-width: 768px) {
    .lg-message {
      min-width: 300px;
      width: 90%;
      padding: 12px 15px;

      &__text {
        font-size: 14px;
      }

      i {
        font-size: 18px;
      }
    }
  }
</style>
